package org.goldenport.g3.servlet

import scala.collection.mutable.ArrayBuffer
import javax.servlet._
import javax.servlet.http._
import com.asamioffice.goldenport.util.OptionUtil.lift
import org.goldenport.g3._
import org.goldenport.g3.admin.G3AuthAdmin
import org.goldenport.g3.messages._
import org.goldenport.g3.messages.http._
import G3Servlet._

/*
 * @since   Oct. 12, 2010
 * @version Jul.  2, 2011
 * @author  ASAMI, Tomoharu
 */
class G3AuthServlet extends HttpServlet {
  val admin = new G3AuthAdmin

  override def init(config: ServletConfig) {
    open_Application(admin, config)
  }

  protected def open_Application(a: G3AuthAdmin, config: ServletConfig) {
    a.openServlet(config)
  }

  override def destroy() {
    admin.close()
  }

  override def doGet(req: HttpServletRequest, resp: HttpServletResponse) {
    req.getPathInfo match {
      case "/login" => login_page(req, resp)
      case "/logout" => logout_page(req, resp)
      case "/newaccount" => newaccount_page(req, resp)
      case "/updateaccount" => updateaccount_page(req, resp)
      case "/admin/index" => adminindex_page(req, resp)
      case _ => error("doGet:" + req.getPathInfo)
    }
  }

  private def login_page(req: HttpServletRequest, resp: HttpServletResponse) {
    val session = req.getSession
    val message = session.getAttribute(LoginMessage).asInstanceOf[String]
    val username = session.getAttribute(Username).asInstanceOf[String]
//    val r = Record.fromNullables('message -> "MMM",
//                                 'username -> "UUU")
    val r = Record.fromNullables('message -> message,
                                 'username -> username)
    val get = GET("/view/login", r)
    admin.executeHttpResponse(get, resp)
  }

  private def logout_page(req: HttpServletRequest, resp: HttpServletResponse) {
    error("not implemented yet")
  }

  private def newaccount_page(req: HttpServletRequest, resp: HttpServletResponse) {
    val get = GET("/view/newaccount", req)
    admin.executeHttpResponse(get, resp)
  }

  private def updateaccount_page(req: HttpServletRequest, resp: HttpServletResponse) {
    val get = GET("/view/updateaccount", req)
    admin.executeHttpResponse(get, resp)
  }

  private def adminindex_page(req: HttpServletRequest, resp: HttpServletResponse) {
    val get = GET("/admin/index", req)
    admin.executeHttpResponse(get, resp)
  }

  override def doPost(req: HttpServletRequest, resp: HttpServletResponse) {
    req.getPathInfo match {
      case "/login" => exec_login(req, resp)
      case "/logout" => exec_logout(req, resp)
      case "/newaccount" => exec_updateaccount(req, resp)
      case "/updateaccount" => exec_updateaccount(req, resp)
      case "/admin/build" => exec_build(req, resp)
      case "/admin/destroy" => exec_destroy(req, resp)
      case _ => error("doGet:" + req.getPathInfo)
    }
  }

  private def exec_login(req: HttpServletRequest, resp: HttpServletResponse) {
    val username = req.getParameter("username")
    val password = req.getParameter("password")
    val session = req.getSession(true)
    val user = auth_user(lift(username), lift(password))
    val target = user match {
      case Some(u) => {
        session.setAttribute(SessionUser, u)
        session.getAttribute(SessionTarget) match {
          case null => error("XXX")
          case s: String => s
          case _ => error("XXX")
        }
      }
      case None => {
        session.setAttribute(Username, username)
        session.setAttribute(LoginMessage, LoginErrorMessage) // XXX
        loginUri(req)
      }
    }
    resp.sendRedirect(target)
  }

  private def exec_logout(req: HttpServletRequest, resp: HttpServletResponse) {
    error("not implemented yet")
  }

  private def exec_newaccount(req: HttpServletRequest, resp: HttpServletResponse) {
    val post = POST("/newaccount", req)
    admin.invoke(post)
  }

  private def exec_updateaccount(req: HttpServletRequest, resp: HttpServletResponse) {
    val post = POST("/updateaccount", req)
    admin.invoke(post)
  }

  private def exec_build(req: HttpServletRequest, resp: HttpServletResponse) {
    val post = POST("/admin/build", req)
    admin.invoke(post)
  }

  private def exec_destroy(req: HttpServletRequest, resp: HttpServletResponse) {
    val post = POST("/admin/destroy", req)
    admin.invoke(post)
  }

  private def auth_user(username: Option[String], password: Option[String]): Option[G3User] = {
    val r = Record.fromOptions('username -> username,
                               'password -> password)
    val get = Get("/login", r)
    admin.invoke(get, resulter = {
      case user: G3User => user
    }).asInstanceOf[Option[G3User]]
  }
}
